package com.marketlive.entity.account;

/*
(C) Copyright MarketLive. 2006. All rights reserved.
MarketLive is a trademark of MarketLive, Inc.
Warning: This computer program is protected by copyright law and international treaties.
Unauthorized reproduction or distribution of this program, or any portion of it, may result
in severe civil and criminal penalties, and will be prosecuted to the maximum extent
possible under the law.
*/

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.marketlive.entity.IEntityHome;
import org.marketlive.entity.account.IAccountSet;
import org.marketlive.entity.account.IContact;
import org.marketlive.entity.account.ICustomer;
import org.marketlive.entity.account.ICustomerHome;
import org.marketlive.entity.account.IHint;

import com.marketlive.entity.Entity;

/**
 * @inheritDoc
 */
public class Customer extends Entity implements ICustomer {

    /**
     * Entity type constant.
     */
    public static final String ENTITY_TYPE = "customer";

    /**
     * The Customer Home Object Interface.
     */
    private static ICustomerHome entityHome;
    /**
     * The account set this customer belongs to.
     */
    private IAccountSet accountSet;
    /**
     * Email address property.
     */
    private String email;

    /**
     * User name property.
     */
    private String userName;

    /**
     * Password property.
     */
    private String password;

    /**
     * The Hint chosen by this Customer for password recovery.
     */
    private IHint hint;

    /**
     * Hint answer property.
     */
    private String hintAnswer;

    /**
     * Guest status property.
     */
    private boolean guest = true;

    /**
     * Deleted status property.
     */
    private boolean deleted;

    /**
     * Date deleted property.
     */
    private Date dateDeleted;

    /** The contacts linked to this customer. */
    private Set contacts = new LinkedHashSet();

    /** Removed for PCI-DSS **/
    /** The credit cards linked to this customer. */
//    private Set creditCards = new HashSet();

    /** The orders linked to this customer. */
    private Set orders = new HashSet();

    /** Does this customer have contacts in address book. */
    private Set contactsInAddressBook = null;

    /** WishLists assigned to this customer. */
    private List wishLists = new ArrayList();

    private List customerGroups = null;

    /**
     * A key code reference for the encrypted cc number.
     */
    private String keyCode;

    // Name
    private String name;

    // The customer's active locale.
    private String locale;

    /**
     * Set the Entity Home to the given Customer Home Object.
     * @param entityHome - Entity Home Object to use for accounts.
     */
    public static void setEntityHome(final ICustomerHome entityHome) {
        Customer.entityHome = entityHome;
    }

    /**
     * @inheritDoc
     */
    public IEntityHome getEntityHome() {
        return entityHome;
    }

    /**
     * Default constructor.
     */
    public Customer() {
    }

    /**
     * Full constructor. Creates an instance of an account entity with specified email address, user name and password.
     *
     * @param email String value
     * @param userName String value
     * @param password String value
     */
    public Customer(final String email, final String userName, final String password) {
        this.setEmail(email);
        this.setUserName(userName);
        this.setPassword(password);
    }

    /**
     * @inheritDoc
     */
    public IAccountSet getAccountSet() {
        return accountSet;
    }

    /**
     * @inheritDoc
     */
    public void setAccountSet(IAccountSet accountSet) {
        this.accountSet = accountSet;
    }

    /**
     * @inheritDoc
     */
    public String getEmail() {
        return this.email;
    }

    /**
     * @inheritDoc
     */
    public void setEmail(final String email) {
        this.email = email;
    }

    /**
     * @inheritDoc
     */
    public String getUserName() {
        return this.userName;
    }

    /**
     * @inheritDoc
     */
    public void setUserName(final String userName) {
        this.userName = userName;
    }

    /**
     * @inheritDoc
     */
    public String getPassword() {
        return this.password;
    }

    /**
     * @inheritDoc
     */
    public void setPassword(final String password) {
        this.password = password;
    }

    /**
     * @inheritDoc
     */
    public IHint getHint() {
        return this.hint;
    }

    /**
     * @inheritDoc
     */
    public void setHint(IHint hint) {
        this.hint = hint;
    }

    /**
     * @inheritDoc
     */
    public String getHintAnswer() {
        return this.hintAnswer;
    }

    /**
     * @inheritDoc
     */
    public void setHintAnswer(final String hintAnswer) {
        this.hintAnswer = hintAnswer;
    }

    /**
     * @inheritDoc
     */
    public boolean isGuest() {
        return this.guest;
    }

    /**
     * @inheritDoc
     */
    public void setGuest(final boolean guest) {
        this.guest = guest;
    }

    /**
     * @inheritDoc
     */
    public boolean isDeleted() {
        return this.deleted;
    }

    /**
     * @inheritDoc
     */
    public void setDeleted(final boolean deleted) {
        this.deleted = deleted;
    }

    /**
     * @inheritDoc
     */
    public Date getDateDeleted() {
        return this.dateDeleted;
    }

    /**
     * @inheritDoc
     */
    public void setDateDeleted(final Date dateDeleted) {
        this.dateDeleted = dateDeleted;
    }

    /**
     * @inheritDoc
     */
    public String getKeyCode() {
        return keyCode;
    }

    /**
     * @inheritDoc
     */
    public void setKeyCode(String keyCode) {
        this.keyCode = keyCode;
    }

    /**
     * @inheritDoc
     */
    public Set getContacts() {
        return this.contacts;
    }

    /**
     * @inheritDoc
     */
    public void setContacts(final Set contacts) {
        this.contacts = contacts;
        // Reset address book
        this.contactsInAddressBook = null;
    }

    /**
     * @inheritDoc
     */
    // todo Re-sort this list after adding new contact -- BVT.
    public void addContact(final IContact contact) {
        // Return if contact is already on customer's list.
        if (contacts.contains(contact)) {
            return;
        }
        this.contacts.add(contact);

        // Update the contactsInAddressBook collection.
        if ((contact.isInAddressBook()) && (contact.isDeleted() == false)) {
        	this.getContactsInAddressBook().add(contact);
        }
    }

    /**
     * @inheritDoc
     */
    public void removeContact(final IContact contact) {
        Iterator iter = contacts.iterator();
        while (iter.hasNext()) {
            IContact contactInList = (IContact) iter.next();
            if (contact.equals(contactInList)) {
                // contacts.remove(contact);
                // Update the contactsInAddressBook collection.
                if ((contact.isInAddressBook()) && (contact.isDeleted() == true)) {
                    this.getContactsInAddressBook().remove(contact);
                }
                break;
            }
        }
        contact.setCustomer(null);
    }

    /**
     * @inheritDoc
     */
    public void removeAllContacts() {
        this.contacts.clear();

        // Update the contactsInAddressBook collection.
        contactsInAddressBook.clear();
    }

    /**
     * @inheritDoc
     */
    public Set getContactsInAddressBook() {

    	if (this.contactsInAddressBook == null) {
    		
	        // Update the contactsInAddressBook collection.
	        this.contactsInAddressBook = new LinkedHashSet();
	        Iterator iter = this.contacts.iterator();
	        while (iter.hasNext()) {
	            IContact contact = (IContact) iter.next();
	            if ((contact.isInAddressBook()) && (contact.isDeleted() == false)) {
	                this.contactsInAddressBook.add(contact);
	            }
	        }
    	}
    	
        return this.contactsInAddressBook;
    }

    /**
     * @inheritDoc
     */
    public boolean hasContactsInAddressBook() {
        return (this.getContactsInAddressBook().size() > 1 ? true : false);
    }

    /**
     * @inheritDoc
     */
    /** Removed for PCI-DSS **/
//    public Set getCreditCards() {
//        return this.creditCards;
//    }

    /**
     * @inheritDoc
     */
    /** Removed for PCI-DSS **/
//    public void setCreditCards(final Set creditCards) {
//        this.creditCards = creditCards;
//    }

    /**
     * @inheritDoc
     */
    /** Removed for PCI-DSS **/
//    public void addCreditCard(final ICreditCard creditCard) {
//        this.creditCards.add(creditCard);
//    }

    /**
     * @inheritDoc
     */
    /** Removed for PCI-DSS **/
//    public void removeCreditCard(final ICreditCard creditCard) {
//        Iterator iter = this.creditCards.iterator();
//        while (iter.hasNext()) {
//            ICreditCard creditCardInList = (ICreditCard) iter.next();
//            if (creditCard.equals(creditCardInList)) {
//                this.creditCards.remove(creditCardInList);
//                return;
//            }
//        }
//    }

    /**
     * @inheritDoc
     */
    /** Removed for PCI-DSS **/
//    public void removeAllCreditCards() {
//        this.creditCards.clear();
//    }

    /**
     * @inheritDoc
     */
    public Set getOrders() {
        return this.orders;
    }

    /**
     * @inheritDoc
     */
    public void setOrders(final Set orders) {
        this.orders = orders;
    }


    /**
     * @inheritDoc
     */
    public IContact getPrimaryContact() {
        IContact primaryContact = null;
        for (Iterator iter = contacts.iterator(); iter.hasNext();) {
            primaryContact = (IContact) iter.next();
            if (primaryContact.isPrimary()) {
                break;
            }
        }
        return primaryContact;
    }

    /**
     * @inheritDoc
     */
    public List getWishLists() {
        return this.wishLists;
    }

    /**
     * @inheritDoc
     */
    public void setWishLists(List wishLists) {
        this.wishLists = wishLists;
    }

    /**
     * @inheritDoc
     */
    public void removeAllWishLists() {
        this.wishLists.clear();
    }

    /**
     * {@inheritDoc}
     */
    public String getName() {
        return name;
    }

    /**
     * {@inheritDoc}
     */
    public void setName(final String name) {
        this.name = name;
    }

    /**
     * {@inheritDoc}
     */
    public String getLocale() {
        return locale;
    }

    /**
     * {@inheritDoc}
     */
    public void setLocale(String locale) {
        this.locale = locale;
    }


}
